#include "log_api.h"
#include "flash_api.h"
#include "memory_board.h"
#include "cardholder_api.h"
#include "device_parameter.h"

/**
 * @brief 获取持卡人上限
 *
 * @return uint8_t - 持卡人上限
 */
static uint8_t GetCardholderLimit(void);

/**
 * @brief 获取验证开锁时间标识位
 *
 * @return uint8_t - 使能标识
 */
static bool GetValidationStartTimeEnableFlag(void);

/**
 * @brief 写新增持密钥日志
 *
 * @param KeyType     - 密钥类型
 * @param pKeyValueIn - 密钥键值
 * @param KeyToken    - 密钥唯一编码
 */
static void WriteNewKeyLog(const uint8_t KeyType, const uint8_t *pKeyValueIn, const uint32_t KeyToken);

/**
 * @brief 写删除密钥日志
 *
 * @param KeyType     - 密钥类型
 * @param pKeyValueIn - 密钥键值
 * @param KeyToken    - 密钥唯一编码
 */
static void WriteDeleteKeyLog(const uint8_t KeyType, const uint8_t *pKeyValueIn, const uint32_t KeyToken);

/**
 * @brief 写修改密钥日志
 *
 * @param KeyType     - 密钥类型
 * @param pKeyValueIn - 密钥键值
 * @param KeyToken    - 密钥唯一编码
 */
static void WriteChangeKeyLog(const uint8_t KeyType, const uint8_t *pKeyValueIn, const uint32_t KeyToken);

/**
 * @brief 验证密钥类型有效性
 *
 * @param KeyType - 密钥类型
 * @return bool   - 验证状态（true：成功 false：失败）
 */
static bool VerifyKeyTypeValidity(uint8_t KeyType);

/**
 * @brief 验证用户状态是否有效
 *
 * @param Status - 用户状态
 * @return bool  - 验证状态（true：成功 false：失败）
 */
static bool VerifyUserStatus(uint8_t Status);

/**
 * @brief 更新持卡人
 *
 * @param CardholderList - 持卡人序号
 * @param pInformationIn - 持卡人信息
 * @return bool          - 更新状态（true：成功 false：失败）
 */
static bool UpdateCardholder(uint8_t CardholderList, CardholderInformation_t *pInformationIn);

/**
 * @brief 验证密钥有效性
 *
 * @param KeyType      - 密钥类型
 * @param pVerifyKeyIn - 待验证的密钥
 * @param pSourceKeyIn - 与之比对的密钥
 * @param KeyLength    - 密钥长度
 * @return bool        - 验证状态（true：成功 false：失败）
 */
static bool VerifyKeyValidity(const uint8_t KeyType, const void *pVerifyKeyIn, const void *pSourceKeyIn, const uint8_t KeyLength);

/**
 * @brief 验证时间参数是否一致
 *
 * @param OldStartTime     - 旧起始时间
 * @param OldEndTime       - 旧结束时间
 * @param OldDate          - 旧周期
 * @param pOldCycleUnionIn - 旧时间段
 * @param NewStartTime     - 新起始时间
 * @param NewEndTime       - 新结束时间
 * @param NewDate          - 新周期
 * @param pNewCycleUnionIn - 新时间段
 * @return bool            - 验证结果（true：成功 false：失败）
 */
static bool VerifyThatTheTimeParameterAreConsistent(uint32_t OldStartTime, uint32_t OldEndTime, uint8_t OldDate, CycleUnion_t *pOldCycleUnionIn, uint32_t NewStartTime, uint32_t NewEndTime, uint8_t NewDate, CycleUnion_t *pNewCycleUnionIn);

/**
 * @brief 验证持卡人文件中的密钥是否存在
 *
 * @param pInformationIn - 持卡人文件
 * @param KeyType        - 密钥类型
 * @param pKeyValueIn    - 密钥
 * @param pKeyNumberOut  - 验证成功返回对应密钥编码
 * @return bool          - 验证状态（true：成功 false：失败）
 */
static bool VerifyKeyExistsFromTheCardholderFile(CardholderInformation_t *pInformationIn, uint8_t KeyType, const void *pKeyValueIn, uint8_t *pKeyNumberOut);

/**
 * @brief 删除特定类型的密钥
 *
 * @param KeyType                    - 密钥类型
 * @return CardholderCommandResult_t - 删除状态（true：成功 false：失败）
 */
static CardholderCommandResult_t DeletingSpecificTypeOfKey(uint8_t KeyType);

/**
 * @brief 删除所有持卡人
 *
 */
static void DeleteAllCardholder(void);

/**
 * @brief 删除指定用户
 *
 * @param pUserNameIn                - 用户名
 * @return CardholderCommandResult_t - 删除状态（true：成功 false：失败）
 */
static CardholderCommandResult_t DeleteDesignatedCardholder(const uint8_t *pUserNameIn);

/**
 * @brief 删除特定密钥
 *
 * @param KeyType                    - 密钥类型
 * @param pKeyValueIn                - 密钥键值
 * @return CardholderCommandResult_t - 删除状态（true：成功 false：失败）
 */
static CardholderCommandResult_t DeletingSpecificKey(uint8_t KeyType, const void *pKeyValueIn);

/**
 * @brief 删除指定的用户指定类型的密钥
 *
 * @param KeyType                    - 密钥类型
 * @param pUserNameIn                - 用户名
 * @return CardholderCommandResult_t - 删除状态（true：成功 false：失败）
 */
static CardholderCommandResult_t DeleteTheSpecifiedUserSpecificKeyType(const uint8_t KeyType, const uint8_t *pUserNameIn);

/**
 * @brief 删除指定的用户指定类型指定密钥
 *
 * @param KeyType                    - 密钥类型
 * @param pUserNameIn                - 用户名
 * @param pKeyValueIn                - 密钥键值
 * @return CardholderCommandResult_t - 删除状态（true：成功 false：失败）
 */
static CardholderCommandResult_t DeleteTheSpecifiedUserSpecificKey(const uint8_t KeyType, const uint8_t *pUserNameIn, const void *pKeyValueIn);

/**
 * @brief 核实授权时间
 *
 * @param StartTime          - 授权起始时间
 * @param EndTime            - 授权结束时间
 * @param Date               - 授权周期
 * @param pTimePeriodIn      - 时间段
 * @return bool              - 验证状态（true：成功 false：失败）
 */
static bool VerificationOfAuthorisationTime(const uint32_t StartTime, const uint32_t EndTime, const uint8_t Date, CycleUnion_t *pTimePeriodIn);

static uint8_t GetCardholderLimit(void)
{
  return GetNumberOfCardholder();
}

static bool GetValidationStartTimeEnableFlag(void)
{
  return GetStartTimeVerifyEn();
}

static void WriteNewKeyLog(const uint8_t KeyType, const uint8_t *pKeyValueIn, const uint32_t KeyToken)
{
  uint8_t LogAttachedParameters[LOG_DATA_PACKET_LENGTH] = {0};

  if (KeyType == CARD_AUTHENTICATION)
  {
    if (pKeyValueIn != NULL)
    {
      memcpy(LogAttachedParameters, pKeyValueIn, USER_AUTHENTICATION_KEY_LENGTH);
    }
  }
  else
  {
    LogAttachedParameters[0] = (uint8_t)((KeyToken & 0xFF000000) >> 24);
    LogAttachedParameters[1] = (uint8_t)((KeyToken & 0x00FF0000) >> 16);
    LogAttachedParameters[2] = (uint8_t)((KeyToken & 0x0000FF00) >> 8);
    LogAttachedParameters[3] = (uint8_t)(KeyToken & 0x000000FF);
  }

  WriteAddNewCardholderLog(KeyType, LogAttachedParameters, LOG_DATA_PACKET_LENGTH);
}

static void WriteDeleteKeyLog(const uint8_t KeyType, const uint8_t *pKeyValueIn, const uint32_t KeyToken)
{
  uint8_t LogAttachedParameters[LOG_DATA_PACKET_LENGTH] = {0};

  if (KeyType == CARD_AUTHENTICATION)
  {
    if (pKeyValueIn != NULL)
    {
      memcpy(LogAttachedParameters, pKeyValueIn, USER_AUTHENTICATION_KEY_LENGTH);
    }
  }
  else
  {
    LogAttachedParameters[0] = (uint8_t)((KeyToken & 0xFF000000) >> 24);
    LogAttachedParameters[1] = (uint8_t)((KeyToken & 0x00FF0000) >> 16);
    LogAttachedParameters[2] = (uint8_t)((KeyToken & 0x0000FF00) >> 8);
    LogAttachedParameters[3] = (uint8_t)(KeyToken & 0x000000FF);
  }

  WriteDeleteTheCardholderLog(KeyType, LogAttachedParameters, LOG_DATA_PACKET_LENGTH);
}

static void WriteChangeKeyLog(const uint8_t KeyType, const uint8_t *pKeyValueIn, const uint32_t KeyToken)
{
  uint8_t LogAttachedParameters[LOG_DATA_PACKET_LENGTH] = {0};

  if (KeyType == CARD_AUTHENTICATION)
  {
    if (pKeyValueIn != NULL)
    {
      memcpy(LogAttachedParameters, pKeyValueIn, USER_AUTHENTICATION_KEY_LENGTH);
    }
  }
  else
  {
    LogAttachedParameters[0] = (uint8_t)((KeyToken & 0xFF000000) >> 24);
    LogAttachedParameters[1] = (uint8_t)((KeyToken & 0x00FF0000) >> 16);
    LogAttachedParameters[2] = (uint8_t)((KeyToken & 0x0000FF00) >> 8);
    LogAttachedParameters[3] = (uint8_t)(KeyToken & 0x000000FF);
  }

  WriteChangeTheCardholderLog(KeyType, LogAttachedParameters, LOG_DATA_PACKET_LENGTH);
}

static bool VerifyUserStatus(uint8_t Status)
{
  switch (Status)
  {
  case NORMAL_USE:
  case BLACKLIST_KEY:
    return true;
  }

  return false;
}

static bool VerifyKeyTypeValidity(uint8_t KeyType)
{
  switch (KeyType)
  {
  case CARD_AUTHENTICATION:
  case FACE_ID_AUTHENTICATION:
  case PASSWORD_AUTHENTICATION:
  case FINGER_PRINTF_AUTHENTICATION:
  case BLUETOOTH_VIRTUAL_CARD_AUTHENTICATION:
    return true;
  }

  return false;
}

static bool UpdateCardholder(uint8_t CardholderList, CardholderInformation_t *pInformationIn)
{
  if (pInformationIn != NULL)
  {
    return FlashWriteCardHolderFile(CardholderList * sizeof(CardholderInformation_t), pInformationIn, sizeof(CardholderInformation_t));
  }

  return false;
}

static bool VerifyKeyValidity(const uint8_t KeyType, const void *pVerifyKeyIn, const void *pSourceKeyIn, const uint8_t KeyLength)
{
  char TmpPassword[TYPE_THE_LENGTH_OF_KEY] = {0};

  if ((pVerifyKeyIn != NULL) && (pSourceKeyIn != NULL))
  {
    if ((KeyLength > 0) && (KeyLength <= TYPE_THE_LENGTH_OF_KEY))
    {
      switch (KeyType)
      {
      case CARD_AUTHENTICATION:
      case FACE_ID_AUTHENTICATION:
      case FINGER_PRINTF_AUTHENTICATION:
      {
        if (memcmp(pVerifyKeyIn, pSourceKeyIn, USER_AUTHENTICATION_KEY_LENGTH) == 0)
          return true;
      }
      break;

      case PASSWORD_AUTHENTICATION:
      {
        if (KeyLength >= NUMBER_OF_KEYBOARD_KEY)
        {
          const char *pVerifyKeyValue = (const char *)pVerifyKeyIn, *pSourceKeyValue = (const char *)pSourceKeyIn;

          memcpy(TmpPassword, pVerifyKeyIn, KeyLength);
          if (strstr(pVerifyKeyValue, pSourceKeyValue) != NULL)
            return true;
        }
      }
      break;
      }
    }
  }

  return false;
}

static bool VerifyThatTheTimeParameterAreConsistent(uint32_t OldStartTime, uint32_t OldEndTime, uint8_t OldDate, CycleUnion_t *pOldCycleUnionIn, uint32_t NewStartTime, uint32_t NewEndTime, uint8_t NewDate, CycleUnion_t *pNewCycleUnionIn)
{
  if ((pOldCycleUnionIn != NULL) && (pNewCycleUnionIn != NULL))
  {
    uint8_t Count = 0;

    while (Count < MAX_TIME_SLOTS)
    {
      if (pOldCycleUnionIn[Count].BasicCycle != pNewCycleUnionIn[Count].BasicCycle)
        break;

      Count++;
    }

    if (Count == MAX_TIME_SLOTS)
    {
      if (OldStartTime == NewStartTime)
      {
        if (OldEndTime == NewEndTime)
        {
          if (OldDate == NewDate)
            return true;
        }
      }
    }
  }

  return false;
}

static bool VerifyKeyExistsFromTheCardholderFile(CardholderInformation_t *pInformationIn, uint8_t KeyType, const void *pKeyValueIn, uint8_t *pKeyNumberOut)
{
  if ((pInformationIn != NULL) && (pKeyValueIn != NULL))
  {
    for (uint8_t KeyNumber = 0; KeyNumber < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; KeyNumber++)
    {
      if (pInformationIn->KeyInformation[KeyNumber].AuthenticationType == KeyType)
      {
        if (memcmp(pInformationIn->KeyInformation[KeyNumber].AuthenticationKey, pKeyValueIn, USER_AUTHENTICATION_KEY_LENGTH) == 0)
        {
          if (pKeyNumberOut != NULL)
          {
            *pKeyNumberOut = KeyNumber;
          }

          return true;
        }
      }
    }
  }

  return false;
}

static CardholderCommandResult_t DeletingSpecificTypeOfKey(uint8_t KeyType)
{
  bool UpdateCardholderProfileEn = false;
  CardholderInformation_t Cardholder = {0};
  uint8_t NumberOfCardholders = GetCardholderLimit();
  CardholderCommandResult_t DeleteResult = UNKNOWN_KEY_TYPE;

  if (VerifyKeyTypeValidity(KeyType) == true)
  {
    DeleteResult = DELETED_SUCCESSFULLY;

    for (uint8_t CatalogueId = 0; CatalogueId < NumberOfCardholders; CatalogueId++)
    {
      FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), &Cardholder, sizeof(CardholderInformation_t));

      if (VerifyUserStatus(Cardholder.UserInformation.Status) == true)
      {
        for (uint8_t KeyNumber = 0; KeyNumber < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; KeyNumber++)
        {
          if (Cardholder.KeyInformation[KeyNumber].AuthenticationType == KeyType)
          {
            UpdateCardholderProfileEn = true;

            Cardholder.UserInformation.NumberOfKey--;
            if (Cardholder.UserInformation.NumberOfKey == 0)
            {
              memset(&Cardholder, 0, sizeof(CardholderInformation_t));
              break;
            }
            else
            {
              WriteDeleteKeyLog(Cardholder.KeyInformation[KeyNumber].AuthenticationType, Cardholder.KeyInformation[KeyNumber].AuthenticationKey, Cardholder.KeyInformation[KeyNumber].KeyToken);
              memset(&Cardholder.KeyInformation[KeyNumber], 0, sizeof(KeyInformation_t));
            }
          }
        }
      }

      if (UpdateCardholderProfileEn == true)
      {
        UpdateCardholderProfileEn = false;
        UpdateCardholder(CatalogueId, &Cardholder);
      }
    }

    if ((KeyType == FINGER_PRINTF_AUTHENTICATION) || (KeyType == FACE_ID_AUTHENTICATION))
    {
      MemoryDeleteAllUserFromExternalModule();
    }
  }

  return DeleteResult;
}

static void DeleteAllCardholder(void)
{
  InitialiseCardholderDirectory();
  MemoryDeleteAllUserFromExternalModule();
}

static CardholderCommandResult_t DeleteDesignatedCardholder(const uint8_t *pUserNameIn)
{
  uint8_t CardholderListId = 0;
  CardholderInformation_t Cardholder = {0};

  if (FindCardholder(pUserNameIn, &CardholderListId, &Cardholder) == true)
  {
    for (uint8_t i = 0; i < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; i++)
    {
      // 遍历该用户名下是个有外部模组的密钥
      if ((Cardholder.KeyInformation[i].AuthenticationType == FINGER_PRINTF_AUTHENTICATION) || (Cardholder.KeyInformation[i].AuthenticationType == FACE_ID_AUTHENTICATION))
      {
        MemoryDeleteSpecificUserFromExternalModule(Cardholder.KeyInformation[i].AuthenticationKey);
      }

      WriteDeleteKeyLog(Cardholder.KeyInformation[i].AuthenticationType, Cardholder.KeyInformation[i].AuthenticationKey, Cardholder.KeyInformation[i].KeyToken);
    }

    memset(&Cardholder, 0, sizeof(CardholderInformation_t));
    UpdateCardholder(CardholderListId, &Cardholder);

    return DELETED_SUCCESSFULLY;
  }

  return USER_NO_FOUND;
}

static CardholderCommandResult_t DeletingSpecificKey(uint8_t KeyType, const void *pKeyValueIn)
{
  CardholderInformation_t Cardholder = {0};
  CardholderCommandResult_t DeleteResult = OPERATION_ERROR;
  uint8_t KeyNumber = 0, NumberOfCardholders = GetCardholderLimit();

  if (pKeyValueIn != NULL)
  {
    DeleteResult = UNKNOWN_KEY_TYPE;

    if (VerifyKeyTypeValidity(KeyType) == true)
    {
      DeleteResult = DELETED_SUCCESSFULLY;

      for (uint8_t CatalogueId = 0; CatalogueId < NumberOfCardholders; CatalogueId++)
      {
        FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), &Cardholder, sizeof(CardholderInformation_t));

        if (VerifyUserStatus(Cardholder.UserInformation.Status) == true)
        {
          if (VerifyKeyExistsFromTheCardholderFile(&Cardholder, KeyType, pKeyValueIn, &KeyNumber) == true)
          {
            {
              if ((KeyType == FINGER_PRINTF_AUTHENTICATION) || (KeyType == FACE_ID_AUTHENTICATION))
              {
                MemoryDeleteSpecificUserFromExternalModule(pKeyValueIn);
              }

              WriteDeleteKeyLog(Cardholder.KeyInformation[KeyNumber].AuthenticationType, Cardholder.KeyInformation[KeyNumber].AuthenticationKey, Cardholder.KeyInformation[KeyNumber].KeyToken);
            }

            {
              Cardholder.UserInformation.NumberOfKey--;
              (Cardholder.UserInformation.NumberOfKey == 0) ? memset(&Cardholder, 0, sizeof(CardholderInformation_t)) : memset(&Cardholder.KeyInformation[KeyNumber], 0, sizeof(KeyInformation_t));
              UpdateCardholder(CatalogueId, &Cardholder);
            }

            break;
          }
        }
      }
    }
  }

  return DeleteResult;
}

static CardholderCommandResult_t DeleteTheSpecifiedUserSpecificKeyType(const uint8_t KeyType, const uint8_t *pUserNameIn)
{
  CardholderInformation_t Cardholder = {0};
  CardholderCommandResult_t DeleteResult = OPERATION_ERROR;
  uint8_t CatalogueId = 0, NumberOfCardholders = GetCardholderLimit();

  if (pUserNameIn != NULL)
  {
    DeleteResult = UNKNOWN_KEY_TYPE;

    if (VerifyKeyTypeValidity(KeyType) == true)
    {
      DeleteResult = USER_NO_FOUND;

      if (FindCardholder(pUserNameIn, &CatalogueId, &Cardholder) == true)
      {
        DeleteResult = DELETED_SUCCESSFULLY;

        for (uint8_t KeyNumber = 0; KeyNumber < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; KeyNumber++)
        {
          if (Cardholder.KeyInformation[KeyNumber].AuthenticationType == KeyType)
          {
            {
              if ((Cardholder.KeyInformation[KeyNumber].AuthenticationType == FINGER_PRINTF_AUTHENTICATION) || (Cardholder.KeyInformation[KeyNumber].AuthenticationType == FACE_ID_AUTHENTICATION))
              {
                MemoryDeleteSpecificUserFromExternalModule(Cardholder.KeyInformation[KeyNumber].AuthenticationKey);
              }
            }

            {
              WriteDeleteKeyLog(Cardholder.KeyInformation[KeyNumber].AuthenticationType, Cardholder.KeyInformation[KeyNumber].AuthenticationKey, Cardholder.KeyInformation[KeyNumber].KeyToken);
              memset(&Cardholder.KeyInformation[KeyNumber], 0, sizeof(KeyInformation_t));

              Cardholder.UserInformation.NumberOfKey--;
              if (Cardholder.UserInformation.NumberOfKey == 0)
              {
                memset(&Cardholder, 0, sizeof(CardholderInformation_t));
                break;
              }
            }
          }
        }

        UpdateCardholder(CatalogueId, &Cardholder);
      }
    }
  }

  return DeleteResult;
}

static CardholderCommandResult_t DeleteTheSpecifiedUserSpecificKey(const uint8_t KeyType, const uint8_t *pUserNameIn, const void *pKeyValueIn)
{
  CardholderInformation_t Cardholder = {0};
  uint8_t CardholderListId = 0, KeyNumber = 0;
  CardholderCommandResult_t DeleteResult = OPERATION_ERROR;

  if ((pUserNameIn != NULL) && (pKeyValueIn != NULL))
  {
    DeleteResult = UNKNOWN_KEY_TYPE;

    if (VerifyKeyTypeValidity(KeyType) == true)
    {
      DeleteResult = USER_NO_FOUND;

      if (FindCardholder(pUserNameIn, &CardholderListId, &Cardholder) == true)
      {
        DeleteResult = DELETED_SUCCESSFULLY;

        if (VerifyKeyExistsFromTheCardholderFile(&Cardholder, KeyType, pKeyValueIn, &KeyNumber) == true)
        {
          {
            if ((Cardholder.KeyInformation[KeyNumber].AuthenticationType == FINGER_PRINTF_AUTHENTICATION) || (Cardholder.KeyInformation[KeyNumber].AuthenticationType == FACE_ID_AUTHENTICATION))
            {
              MemoryDeleteSpecificUserFromExternalModule(Cardholder.KeyInformation[KeyNumber].AuthenticationKey);
            }
          }

          {
            WriteDeleteKeyLog(Cardholder.KeyInformation[KeyNumber].AuthenticationType, Cardholder.KeyInformation[KeyNumber].AuthenticationKey, Cardholder.KeyInformation[KeyNumber].KeyToken);

            Cardholder.UserInformation.NumberOfKey--;
            (Cardholder.UserInformation.NumberOfKey == 0) ? memset(&Cardholder, 0, sizeof(CardholderInformation_t)) : memset(&Cardholder.KeyInformation[KeyNumber], 0, sizeof(KeyInformation_t));
            UpdateCardholder(CardholderListId, &Cardholder);
          }
        }
      }
    }
  }

  return DeleteResult;
}

static bool VerificationOfAuthorisationTime(const uint32_t StartTime, const uint32_t EndTime, const uint8_t Date, CycleUnion_t *pTimePeriodIn)
{
  CycleUnion_t *pCycleUnion = NULL;
  uint8_t Week = 0, Hour = 0, Minute = 0;
  uint16_t AllowableTimeError = GetAllowableTimeError() * 60;
  uint32_t StartTimestamp = 0, EndTimestamp = 0, NowTimestamp = 0;

  if (pTimePeriodIn != NULL)
  {
    if (EndTime > StartTime)
    {
      NowTimestamp = MemoryGetTimestamp();
      StartTimestamp = (AllowableTimeError < StartTime) ? (StartTime - AllowableTimeError) : StartTime;
      EndTimestamp = ((UINT32_MAX - AllowableTimeError) >= EndTime) ? (EndTime + AllowableTimeError) : EndTime;

      if ((StartTimestamp <= NowTimestamp) || (GetValidationStartTimeEnableFlag() == false))
      {
        if (EndTimestamp >= NowTimestamp)
        {
          MemoryGetTheCurrentTime(NULL, NULL, NULL, &Hour, &Minute, NULL, &Week);

          if ((Date == 0) || (Date & (1 << Week)))
          {
            // 验证时间段是否为空
            {
              uint8_t TimePeriod = 0;

              for (TimePeriod = 0; TimePeriod < MAX_TIME_SLOTS; TimePeriod++)
              {
                if (pTimePeriodIn[TimePeriod].BasicCycle != 0)
                  break;
              }

              if (TimePeriod >= MAX_TIME_SLOTS)
                return true;
            }

            // 验证时间段是否有效
            {
              for (uint8_t i = 0; i < MAX_TIME_SLOTS; i++)
              {
                pCycleUnion = &pTimePeriodIn[i];
                if (pCycleUnion->BasicCycle != 0)
                {
                  NowTimestamp = (Hour * 60) + Minute;
                  EndTimestamp = (pCycleUnion->TimeCycle.EndHour * 60) + pCycleUnion->TimeCycle.EndMinute;
                  StartTimestamp = (pCycleUnion->TimeCycle.StartHour * 60) + pCycleUnion->TimeCycle.StartMinute;

                  if (EndTimestamp <= StartTimestamp)
                  {
                    EndTimestamp += 24 * 60;
                  }

                  if (NowTimestamp < StartTimestamp)
                  {
                    NowTimestamp += 24 * 60;
                  }

                  if ((NowTimestamp >= StartTimestamp) && (NowTimestamp < EndTimestamp))
                    return true;
                }
              }
            }
          }
        }
      }
    }
  }

  return false;
}

bool FindEmptyCardholderCatalogues(uint8_t *pCatalogueIdOut)
{
  CardholderInformation_t Cardholder = {0};
  uint8_t NumberOfCardholders = GetCardholderLimit();

  for (uint8_t CatalogueId = 0; CatalogueId < NumberOfCardholders; CatalogueId++)
  {
    FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), &Cardholder, sizeof(CardholderInformation_t));

    if (VerifyUserStatus(Cardholder.UserInformation.Status) != true)
    {
      if (pCatalogueIdOut != NULL)
      {
        *pCatalogueIdOut = CatalogueId;
      }

      return true;
    }
  }

  return false;
}

bool FindCardholder(const uint8_t *pUserNameIn, uint8_t *pListIdOut, CardholderInformation_t *pInformationOut)
{
  if (pUserNameIn != NULL)
  {
    CardholderInformation_t Cardholder = {0};

    uint8_t NumberOfCardholders = GetCardholderLimit();
    for (uint8_t CatalogueId = 0; CatalogueId < NumberOfCardholders; CatalogueId++)
    {
      FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), &Cardholder, sizeof(CardholderInformation_t));

      if (VerifyUserStatus(Cardholder.UserInformation.Status) == true)
      {
        if (memcmp(pUserNameIn, Cardholder.UserInformation.UserName, CARDHOLDER_USER_NAME_LENGTH) == 0)
        {
          if (pListIdOut != NULL)
          {
            *pListIdOut = CatalogueId;
          }

          if (pInformationOut != NULL)
          {
            memcpy(pInformationOut, &Cardholder, sizeof(CardholderInformation_t));
          }

          return true;
        }
      }
    }
  }

  return false;
}

void InitialiseCardholderDirectory(void)
{
  uint8_t VirtualKeyValue[LOG_DATA_PACKET_LENGTH] = {0};

  FlashDeleteCardHolderFile();
  memset(VirtualKeyValue, VIRTUAL_VALUE, LOG_DATA_PACKET_LENGTH);
  WriteDeleteKeyLog(VIRTUAL_VALUE, VirtualKeyValue, VIRTUAL_VALUE);
}

bool QueryIfTheKeyAlreadyExists(const uint8_t KeyType, const uint8_t *pUserNameIn, const void *pKeyValueIn, CardholderInformation_t *pInformationOut)
{
  uint8_t CardholderListId = 0;
  CardholderInformation_t Cardholder = {0};

  if (pKeyValueIn != NULL)
  {
    if (VerifyKeyTypeValidity(KeyType) == true)
    {
      if (FindCardholder(pUserNameIn, &CardholderListId, &Cardholder) == true)
      {
        if (VerifyKeyExistsFromTheCardholderFile(&Cardholder, KeyType, pKeyValueIn, NULL) == true)
        {
          if (pInformationOut != NULL)
          {
            memcpy(pInformationOut, &Cardholder, sizeof(CardholderInformation_t));
          }

          return true;
        }
      }
    }
  }

  return false;
}

uint16_t QueryTheNumberOfCorrespondingUserKeys(const uint8_t *pUserNameIn)
{
  uint16_t NumberOfKeys = 0;
  CardholderInformation_t Cardholder = {0};
  uint8_t TmpDataBuff[CARDHOLDER_USER_NAME_LENGTH] = {0};

  if (pUserNameIn != NULL)
  {
    memset(TmpDataBuff, VIRTUAL_VALUE, CARDHOLDER_USER_NAME_LENGTH);
    if (memcmp(pUserNameIn, TmpDataBuff, CARDHOLDER_USER_NAME_LENGTH) == 0)
    {
      uint8_t NumberOfCardholders = GetCardholderLimit();
      for (uint8_t CatalogueId = 0; CatalogueId < NumberOfCardholders; CatalogueId++)
      {
        FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), &Cardholder, sizeof(CardholderInformation_t));

        if (VerifyUserStatus(Cardholder.UserInformation.Status) == true)
        {
          NumberOfKeys += Cardholder.UserInformation.NumberOfKey;
        }
      }
    }
    else
    {
      if (FindCardholder(pUserNameIn, NULL, &Cardholder) == true)
      {
        NumberOfKeys = Cardholder.UserInformation.NumberOfKey;
      }
    }
  }

  return NumberOfKeys;
}

uint8_t GetRegisteredCardholderSerialNumber(uint8_t *pSerialNumberOut)
{
  uint16_t NumberOfKeys = 0;
  CardholderInformation_t Cardholder = {0};
  uint8_t NumberOfRegisteredCardholders = 0, NumberOfCardholders = GetCardholderLimit();

  for (uint8_t CatalogueId = 0; CatalogueId < NumberOfCardholders; CatalogueId++)
  {
    FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), &Cardholder, sizeof(CardholderInformation_t));

    if (VerifyUserStatus(Cardholder.UserInformation.Status) == true)
    {
      if (pSerialNumberOut != NULL)
      {
        pSerialNumberOut[NumberOfRegisteredCardholders] = CatalogueId;
      }

      NumberOfRegisteredCardholders++;
    }
  }

  return NumberOfRegisteredCardholders;
}

bool ObtainingCardholderInformationForTargetCatalogue(const uint8_t CatalogueId, CardholderInformation_t *pInformationOut)
{
  if (pInformationOut != NULL)
  {
    uint8_t NumberOfCardholders = GetCardholderLimit();
    if (CatalogueId < NumberOfCardholders)
    {
      FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), pInformationOut, sizeof(CardholderInformation_t));
      return true;
    }
  }

  return false;
}

bool GetUserKeyInformation(const uint8_t *pUserNameIn, CardholderInformation_t *pInformationOut)
{
  if (FindCardholder(pUserNameIn, NULL, pInformationOut))
    return true;

  return false;
}

CardholderCommandResult_t DeleteCardholders(const uint8_t KeyType, const uint8_t *pUserNameIn, const void *pKeyValueIn)
{
  uint8_t TmpDataBuff[CARDHOLDER_USER_NAME_LENGTH] = {0};
  CardholderCommandResult_t ExecuteResult = DELETED_SUCCESSFULLY;
  bool ValidForAllUser = false, ValidForAllUserKey = false, ValidForAllKeyType = false;

  {
    memset(TmpDataBuff, VIRTUAL_VALUE, CARDHOLDER_USER_NAME_LENGTH);

    if (KeyType == VIRTUAL_VALUE)
      ValidForAllKeyType = true;

    if (memcmp(pUserNameIn, TmpDataBuff, CARDHOLDER_USER_NAME_LENGTH) == 0)
      ValidForAllUser = true;

    if (memcmp(pKeyValueIn, TmpDataBuff, USER_AUTHENTICATION_KEY_LENGTH) == 0)
      ValidForAllUserKey = true;
  }

  {
    // 删除所有持卡人
    if ((ValidForAllUser == true) && (ValidForAllUserKey == true) && (ValidForAllKeyType == true))
    {
      DeleteAllCardholder();
    }
    // 删除特定用户
    else if ((ValidForAllUser != true) && (ValidForAllUserKey == true) && (ValidForAllKeyType == true))
    {
      ExecuteResult = DeleteDesignatedCardholder(pUserNameIn);
    }
    // 删除特定密钥类型
    else if ((ValidForAllUser == true) && (ValidForAllUserKey == true) && (ValidForAllKeyType != true))
    {
      ExecuteResult = DeletingSpecificTypeOfKey(KeyType);
    }
    // 删除特定密钥
    else if ((ValidForAllUser == true) && (ValidForAllUserKey != true) && (ValidForAllKeyType != true))
    {
      ExecuteResult = DeletingSpecificKey(KeyType, pKeyValueIn);
    }
    // 删除特定用户特定类型的密钥
    else if ((ValidForAllUser != true) && (ValidForAllUserKey == true) && (ValidForAllKeyType != true))
    {
      DeleteTheSpecifiedUserSpecificKeyType(KeyType, pUserNameIn);
    }
    // 删除特定用户的特定类型特定密钥
    else if ((ValidForAllUser != true) && (ValidForAllUserKey != true) && (ValidForAllKeyType != true))
    {
      ExecuteResult = DeleteTheSpecifiedUserSpecificKey(KeyType, pUserNameIn, pKeyValueIn);
    }
    else
    {
      ExecuteResult = DELETE_FAILED;
    }
  }

  return ExecuteResult;
}

CardholderCommandResult_t NewCardholders(const uint8_t *pUserNameIn, KeyInformation_t *pKeyInformationIn)
{
  CardholderInformation_t Cardholder = {0};
  uint8_t CardholderListId = 0, KeyNumber = 0;
  CardholderCommandResult_t ExecuteResult = ENTRY_FAILURE;

  if ((pUserNameIn != NULL) && (pKeyInformationIn != NULL))
  {
    if (pKeyInformationIn->EndTimestamp >= pKeyInformationIn->StartTimestamp)
    {
      if (((pKeyInformationIn->Count >= MIX_NUMBER_OF_USE) && (pKeyInformationIn->Count <= MAX_NUMBER_OF_USE)) || (pKeyInformationIn->Count == USE_UNLIMITED_TIMES))
      {
        ExecuteResult = UNKNOWN_KEY_TYPE;

        if (VerifyKeyTypeValidity(pKeyInformationIn->AuthenticationType) == true)
        {
          ExecuteResult = ENTRY_FAILURE;

          if (FindCardholder(pUserNameIn, &CardholderListId, &Cardholder) == true)
          {
            if (VerifyKeyExistsFromTheCardholderFile(&Cardholder, pKeyInformationIn->AuthenticationType, pKeyInformationIn->AuthenticationKey, &KeyNumber) == true)
            {
              ExecuteResult = KEY_ALREADY_EXISTS;

              if (memcmp(&Cardholder.KeyInformation[KeyNumber], pKeyInformationIn, sizeof(KeyInformation_t)) != true)
              {
                ExecuteResult = RECORD_SUCCESSFULLY;
                memcpy(&Cardholder.KeyInformation[KeyNumber], pKeyInformationIn, sizeof(KeyInformation_t));
              }
            }
            else
            {
              ExecuteResult = OVER_OF_SINGLE_USER_REGISTER_KEY;

              if (Cardholder.UserInformation.NumberOfKey < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER)
              {
                ExecuteResult = RECORD_SUCCESSFULLY;
                memcpy(&Cardholder.KeyInformation[Cardholder.UserInformation.NumberOfKey++], pKeyInformationIn, sizeof(KeyInformation_t));
              }
            }
          }
          else
          {
            ExecuteResult = CARD_HOLDER_FULL;

            if (FindEmptyCardholderCatalogues(&CardholderListId) == true)
            {
              DeletingSpecificKey(pKeyInformationIn->AuthenticationType, pKeyInformationIn->AuthenticationKey);

              ExecuteResult = RECORD_SUCCESSFULLY;
              memset(&Cardholder, 0, sizeof(CardholderInformation_t));

              Cardholder.UserInformation.NumberOfKey++;
              Cardholder.UserInformation.Status = NORMAL_USE;
              memcpy(Cardholder.UserInformation.UserName, pUserNameIn, CARDHOLDER_USER_NAME_LENGTH);
              memcpy(&Cardholder.KeyInformation, pKeyInformationIn, sizeof(KeyInformation_t));
            }
          }

          if (ExecuteResult == RECORD_SUCCESSFULLY)
          {
            UpdateCardholder(CardholderListId, &Cardholder);
            WriteNewKeyLog(pKeyInformationIn->AuthenticationType, pKeyInformationIn->AuthenticationKey, pKeyInformationIn->KeyToken);
          }
        }
      }
    }
  }

  return ExecuteResult;
}

CardholderCommandResult_t ModifyCardholderInformation(const uint8_t *pUserNameIn, const uint8_t UserStatus, KeyInformation_t *pKeyInformationIn)
{
  CardholderInformation_t Cardholder = {0};
  CardholderCommandResult_t ExecuteResult = ENTRY_FAILURE;
  bool ValidForAllUserKey = false, ValidForAllKeyType = false;
  uint8_t CardholderListId = 0, TmpDataBuff[USER_AUTHENTICATION_KEY_LENGTH] = {0};

  if ((pUserNameIn != NULL) && (pKeyInformationIn != NULL))
  {
    if (pKeyInformationIn->EndTimestamp >= pKeyInformationIn->StartTimestamp)
    {
      if (((pKeyInformationIn->Count >= MIX_NUMBER_OF_USE) && (pKeyInformationIn->Count <= MAX_NUMBER_OF_USE)) || (pKeyInformationIn->Count == USE_UNLIMITED_TIMES))
      {
        ExecuteResult = USER_NO_FOUND;

        if (FindCardholder(pUserNameIn, &CardholderListId, &Cardholder) == true)
        {
          {
            if (pKeyInformationIn->AuthenticationType == VIRTUAL_VALUE)
              ValidForAllKeyType = true;

            memset(TmpDataBuff, VIRTUAL_VALUE, USER_AUTHENTICATION_KEY_LENGTH);
            if (memcmp(pKeyInformationIn->AuthenticationKey, TmpDataBuff, USER_AUTHENTICATION_KEY_LENGTH) == 0)
              ValidForAllUserKey = true;
          }

          if (UserStatus != VIRTUAL_VALUE)
          {
            ExecuteResult = RECORD_SUCCESSFULLY;

            if (Cardholder.UserInformation.Status != UserStatus)
            {
              Cardholder.UserInformation.Status = UserStatus;
              UpdateCardholder(CardholderListId, &Cardholder);
            }
          }
          else
          {
            {
              // 修改该用户的所有密钥
              if ((ValidForAllKeyType == true) && (ValidForAllUserKey == true))
              {
                ExecuteResult = RECORD_SUCCESSFULLY;

                for (uint8_t i = 0; i < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; i++)
                {
                  Cardholder.KeyInformation[i].Date = pKeyInformationIn->Date;
                  Cardholder.KeyInformation[i].Count = pKeyInformationIn->Count;
                  Cardholder.KeyInformation[i].EndTimestamp = pKeyInformationIn->EndTimestamp;
                  Cardholder.KeyInformation[i].StartTimestamp = pKeyInformationIn->StartTimestamp;

                  for (uint8_t j = 0; j < MAX_TIME_SLOTS; j++)
                  {
                    Cardholder.KeyInformation[i].TimePeriod[j].BasicCycle = pKeyInformationIn->TimePeriod[j].BasicCycle;
                  }

                  WriteChangeKeyLog(Cardholder.KeyInformation[i].AuthenticationType, Cardholder.KeyInformation[i].AuthenticationKey, Cardholder.KeyInformation[i].KeyToken);
                }
              }
              // 修改该用户的特定类型的密钥
              else if ((ValidForAllKeyType != true) && (ValidForAllUserKey == true))
              {
                ExecuteResult = RECORD_SUCCESSFULLY;

                for (uint8_t i = 0; i < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; i++)
                {
                  if (Cardholder.KeyInformation[i].AuthenticationType == pKeyInformationIn->AuthenticationType)
                  {
                    Cardholder.KeyInformation[i].Date = pKeyInformationIn->Date;
                    Cardholder.KeyInformation[i].Count = pKeyInformationIn->Count;
                    Cardholder.KeyInformation[i].EndTimestamp = pKeyInformationIn->EndTimestamp;
                    Cardholder.KeyInformation[i].StartTimestamp = pKeyInformationIn->StartTimestamp;

                    for (uint8_t j = 0; j < MAX_TIME_SLOTS; j++)
                    {
                      Cardholder.KeyInformation[i].TimePeriod[j].BasicCycle = pKeyInformationIn->TimePeriod[j].BasicCycle;
                    }

                    WriteChangeKeyLog(Cardholder.KeyInformation[i].AuthenticationType, Cardholder.KeyInformation[i].AuthenticationKey, Cardholder.KeyInformation[i].KeyToken);
                  }
                }
              }
              // 修改该用户的指定密钥
              else if ((ValidForAllKeyType != true) && (ValidForAllUserKey != true))
              {
                ExecuteResult = ENTRY_FAILURE;

                for (uint8_t i = 0; i < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; i++)
                {
                  if (Cardholder.KeyInformation[i].AuthenticationType == pKeyInformationIn->AuthenticationType)
                  {
                    if (memcmp(Cardholder.KeyInformation[i].AuthenticationKey, pKeyInformationIn->AuthenticationKey, USER_AUTHENTICATION_KEY_LENGTH) == 0)
                    {
                      ExecuteResult = RECORD_SUCCESSFULLY;

                      Cardholder.KeyInformation[i].Date = pKeyInformationIn->Date;
                      Cardholder.KeyInformation[i].Count = pKeyInformationIn->Count;
                      Cardholder.KeyInformation[i].EndTimestamp = pKeyInformationIn->EndTimestamp;
                      Cardholder.KeyInformation[i].StartTimestamp = pKeyInformationIn->StartTimestamp;

                      for (uint8_t j = 0; j < MAX_TIME_SLOTS; j++)
                      {
                        Cardholder.KeyInformation[i].TimePeriod[j].BasicCycle = pKeyInformationIn->TimePeriod[j].BasicCycle;
                      }

                      WriteChangeKeyLog(Cardholder.KeyInformation[i].AuthenticationType, Cardholder.KeyInformation[i].AuthenticationKey, Cardholder.KeyInformation[i].KeyToken);
                      break;
                    }
                  }
                }
              }
            }

            if (ExecuteResult == RECORD_SUCCESSFULLY)
            {
              UpdateCardholder(CardholderListId, &Cardholder);
            }
          }
        }
      }
    }
  }

  return ExecuteResult;
}

CardholderCommandResult_t VerifyTheValidityOfTheTypedKey(const uint8_t KeyType, const void *pKeyValueIn, uint8_t KeyLength, KeyInformation_t *pInformationOut)
{
  if (pKeyValueIn != NULL)
  {
    if ((KeyLength > 0) && (KeyLength <= TYPE_THE_LENGTH_OF_KEY))
    {
      switch (KeyType)
      {
      case CARD_AUTHENTICATION:
      case FACE_ID_AUTHENTICATION:
      case PASSWORD_AUTHENTICATION:
      case FINGER_PRINTF_AUTHENTICATION:
      case BLUETOOTH_VIRTUAL_CARD_AUTHENTICATION:
      {
        CardholderInformation_t Cardholder = {0};
        uint8_t NumberOfCardholders = GetCardholderLimit();

        for (uint8_t CatalogueId = 0; CatalogueId < NumberOfCardholders; CatalogueId++)
        {
          FlashReadCardHolderFile(CatalogueId * sizeof(CardholderInformation_t), &Cardholder, sizeof(CardholderInformation_t));

          for (uint8_t KeyNumber = 0; KeyNumber < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; KeyNumber++)
          {
            if (Cardholder.KeyInformation[KeyNumber].AuthenticationType == KeyType)
            {
              if (VerifyKeyValidity(KeyType, pKeyValueIn, Cardholder.KeyInformation[KeyNumber].AuthenticationKey, KeyLength) == true)
              {
                if (Cardholder.UserInformation.Status == NORMAL_USE)
                {
                  if (Cardholder.KeyInformation[KeyNumber].Count > 0)
                  {
                    if (VerificationOfAuthorisationTime(Cardholder.KeyInformation[KeyNumber].StartTimestamp, Cardholder.KeyInformation[KeyNumber].EndTimestamp,
                                                        Cardholder.KeyInformation[KeyNumber].Date, Cardholder.KeyInformation[KeyNumber].TimePeriod) == true)
                    {
                      if (pInformationOut != NULL)
                      {
                        memcpy(pInformationOut, &Cardholder.KeyInformation[KeyNumber], sizeof(KeyInformation_t));
                      }

                      if (Cardholder.KeyInformation[KeyNumber].Count != USE_UNLIMITED_TIMES)
                      {
                        if (Cardholder.KeyInformation[KeyNumber].Count > 0)
                        {
                          Cardholder.KeyInformation[KeyNumber].Count--;
                          UpdateCardholder(CatalogueId, &Cardholder);

                          PRINT("[cardholder]: remaining number of times: %d\r\n", Cardholder.KeyInformation[KeyNumber].Count);
                        }

                        if (Cardholder.KeyInformation[KeyNumber].Count == 0)
                        {
                          PRINT("[cardholder]: reach a predetermined number of times\r\n");
                          DeletingSpecificKey(Cardholder.KeyInformation[KeyNumber].AuthenticationType, Cardholder.KeyInformation[KeyNumber].AuthenticationKey);
                        }
                      }

                      return AUTHENTICATION_SUCCESS;
                    }
                  }

                  return NOT_IN_THE_ALLOWED_TIME;
                }

                return CARDHOLDER_DISABLED;
              }
            }
          }
        }
      }
      break;
      }
    }
  }

  return AUTHENTICATION_FAILURE;
}

CardholderCommandResult_t BluetoothVirtualCardAuthentication(uint8_t *pUserNameIn, uint32_t ValidityPeriod, KeyInformation_t *pKeyInformationIn)
{
  CardholderInformation_t CardholderInformation = {0};
  uint32_t ReplaceId = 0, MemoryReplaceId = 0, NowTimestamp = 0;
  bool RegisterNewUserEn = false, ReplaceAllBluetoothVirtualCardEn = false;
  uint8_t CardholderListId = 0, KeyNumber = 0, NumberOfScanf = GetCardholderLimit();

  if ((pUserNameIn != NULL) && (pKeyInformationIn != NULL))
  {
    if (pKeyInformationIn->AuthenticationType == BLUETOOTH_VIRTUAL_CARD_AUTHENTICATION)
    {
      {
        NowTimestamp = MemoryGetTimestamp();

        ReplaceId = pKeyInformationIn->AuthenticationKey[0] << 24;
        ReplaceId |= pKeyInformationIn->AuthenticationKey[1] << 16;
        ReplaceId |= pKeyInformationIn->AuthenticationKey[2] << 8;
        ReplaceId |= pKeyInformationIn->AuthenticationKey[3];

        if ((pKeyInformationIn->StartTimestamp >= pKeyInformationIn->EndTimestamp) || (NowTimestamp >= pKeyInformationIn->EndTimestamp))
          return NOT_IN_THE_ALLOWED_TIME;

        uint8_t NumbeOfTraversals = 0;
        while (NumbeOfTraversals < NumberOfScanf)
        {
          FlashReadCardHolderFile(NumbeOfTraversals * sizeof(CardholderInformation_t), &CardholderInformation, sizeof(CardholderInformation_t));
          if (VerifyUserStatus(CardholderInformation.UserInformation.Status) == true)
          {
            for (uint8_t i = 0; i < MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER; i++)
            {
              if (CardholderInformation.KeyInformation[i].AuthenticationType == BLUETOOTH_VIRTUAL_CARD_AUTHENTICATION)
              {
                MemoryReplaceId = CardholderInformation.KeyInformation[i].AuthenticationKey[0] << 24;
                MemoryReplaceId |= CardholderInformation.KeyInformation[i].AuthenticationKey[1] << 16;
                MemoryReplaceId |= CardholderInformation.KeyInformation[i].AuthenticationKey[2] << 8;
                MemoryReplaceId |= CardholderInformation.KeyInformation[i].AuthenticationKey[3];

                if (ReplaceId < MemoryReplaceId)
                  return OPERATION_ERROR;

                if (ReplaceId > MemoryReplaceId)
                {
                  RegisterNewUserEn = true;
                  ReplaceAllBluetoothVirtualCardEn = true;
                }

                break;
              }
            }
          }

          NumbeOfTraversals++;
        }

        if (NumbeOfTraversals == NumberOfScanf)
          RegisterNewUserEn = true;
      }

      if ((RegisterNewUserEn == true) || (ReplaceAllBluetoothVirtualCardEn == true))
      {
        if (abs((int)(NowTimestamp - ValidityPeriod)) > VIRUAL_CARD_ACTIVATION_EFFECTIVE_TIME)
          return OPERATION_ERROR;

        if (ReplaceAllBluetoothVirtualCardEn == true)
        {
          DeletingSpecificTypeOfKey(BLUETOOTH_VIRTUAL_CARD_AUTHENTICATION);
        }

        if (RegisterNewUserEn == true)
        {
          if (FindCardholder(pUserNameIn, &CardholderListId, &CardholderInformation) == true)
          {
            if (VerifyKeyExistsFromTheCardholderFile(&CardholderInformation, pKeyInformationIn->AuthenticationType, pKeyInformationIn->AuthenticationKey, &KeyNumber) == true)
            {
              bool ModifiedEn = VerifyThatTheTimeParameterAreConsistent(CardholderInformation.KeyInformation[KeyNumber].StartTimestamp,
                                                                        CardholderInformation.KeyInformation[KeyNumber].EndTimestamp,
                                                                        CardholderInformation.KeyInformation[KeyNumber].Date,
                                                                        CardholderInformation.KeyInformation[KeyNumber].TimePeriod,
                                                                        pKeyInformationIn->StartTimestamp,
                                                                        pKeyInformationIn->EndTimestamp,
                                                                        pKeyInformationIn->Date,
                                                                        pKeyInformationIn->TimePeriod);

              if (ModifiedEn == false)
              {
                CardholderInformation.KeyInformation[KeyNumber].Date = pKeyInformationIn->Date;
                CardholderInformation.KeyInformation[KeyNumber].Count = pKeyInformationIn->Count;
                CardholderInformation.KeyInformation[KeyNumber].EndTimestamp = pKeyInformationIn->EndTimestamp;
                CardholderInformation.KeyInformation[KeyNumber].StartTimestamp = pKeyInformationIn->StartTimestamp;
                for (uint8_t j = 0; j < MAX_TIME_SLOTS; j++)
                {
                  CardholderInformation.KeyInformation[KeyNumber].TimePeriod[j].BasicCycle = pKeyInformationIn->TimePeriod[j].BasicCycle;
                }

                WriteChangeKeyLog(CardholderInformation.KeyInformation[KeyNumber].AuthenticationType, CardholderInformation.KeyInformation[KeyNumber].AuthenticationKey, CardholderInformation.KeyInformation[KeyNumber].KeyToken);
              }
            }
            else
            {
              if (CardholderInformation.UserInformation.NumberOfKey >= MAX_NUMBER_OF_KEYS_CARRIED_BY_SINGLE_USER)
                return OVER_OF_SINGLE_USER_REGISTER_KEY;

              memcpy(&CardholderInformation.KeyInformation[CardholderInformation.UserInformation.NumberOfKey++], pKeyInformationIn, sizeof(KeyInformation_t));
            }
          }
          else
          {
            if (FindEmptyCardholderCatalogues(&CardholderListId) != true)
              return CARD_HOLDER_FULL;

            {
              memset(&CardholderInformation, 0, sizeof(CardholderInformation_t));
              CardholderInformation.UserInformation.NumberOfKey++;
              CardholderInformation.UserInformation.Status = NORMAL_USE;
              memcpy(CardholderInformation.UserInformation.UserName, pUserNameIn, CARDHOLDER_USER_NAME_LENGTH);
              memcpy(&CardholderInformation.KeyInformation, pKeyInformationIn, sizeof(KeyInformation_t));

              UpdateCardholder(CardholderListId, &CardholderInformation);
              WriteNewKeyLog(pKeyInformationIn->AuthenticationType, pKeyInformationIn->AuthenticationKey, pKeyInformationIn->KeyToken);
            }
          }
        }
      }

      if (VerificationOfAuthorisationTime(pKeyInformationIn->StartTimestamp, pKeyInformationIn->EndTimestamp, pKeyInformationIn->Date, pKeyInformationIn->TimePeriod) == true)
        return AUTHENTICATION_SUCCESS;

      return AUTHENTICATION_FAILURE;
    }
  }

  return OPERATION_ERROR;
}
